package com.maoatao.easycodegen.framework.model;

import com.maoatao.easycodegen.framework.constant.Operator;
import com.maoatao.easycodegen.framework.constant.Order;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 基础查询
 *
 * @author MaoAtao
 * @date 2025-10-04
 */
@SuppressWarnings("unchecked")
public abstract class BaseQuery<K extends Serializable, Q> extends PageRequest {

    public static final ColumnName ID = new ColumnName("id", "id");

    public static final ColumnName GMT_CREATE = new ColumnName("gmt_create", "gmtCreate");

    public static final ColumnName GMT_MODIFIED = new ColumnName("gmt_modified", "gmtModified");

    private final Map<String, ColumnName> fieldMap = new HashMap<>();

    private final List<Expression> expressions;

    private final List<OrderItem> orders;

    public BaseQuery() {
        this.orders = new ArrayList<>();
        this.expressions = new ArrayList<>();
        initFieldMap();
    }

    public List<Expression> getExpressions() {
        return List.copyOf(expressions);
    }

    public List<OrderItem> getOrders() {
        return List.copyOf(orders);
    }

    // ---------------------- page 条件 start ----------------------

    public Q pageNo(Long pageNo) {
        if (pageNo != null && pageNo > 0) {
            setPageNo(pageNo);
        }
        return (Q) this;
    }

    public Q pageSize(Long pageSize) {
        if (pageSize != null && pageSize > 0) {
            setPageSize(pageSize);
        }
        return (Q) this;
    }

    // ---------------------- page 条件 end ----------------------

    // ---------------------- id 条件 start ----------------------

    /**
     * 添加id等于条件
     *
     * @param id 用户ID
     * @return UserQuery实例，支持链式调用
     */
    public Q idEqualTo(K id) {
        if (id != null) {
            this.expressions.add(new Expression(ID, Operator.EqualTo, List.of(id)));
        }
        return (Q) this;
    }

    /**
     * 添加id不等于条件
     *
     * @param id 用户ID
     * @return UserQuery实例，支持链式调用
     */
    public Q idNotEqualTo(K id) {
        if (id != null) {
            this.expressions.add(new Expression(ID, Operator.NotEqualTo, List.of(id)));
        }
        return (Q) this;
    }

    /**
     * 添加id大于条件
     *
     * @param id 用户ID
     * @return UserQuery实例，支持链式调用
     */
    public Q idGreaterThan(K id) {
        if (id != null) {
            this.expressions.add(new Expression(ID, Operator.GreaterThan, List.of(id)));
        }
        return (Q) this;
    }

    /**
     * 添加id小于条件
     *
     * @param id 用户ID
     * @return UserQuery实例，支持链式调用
     */
    public Q idLessThan(K id) {
        if (id != null) {
            this.expressions.add(new Expression(ID, Operator.LessThan, List.of(id)));
        }
        return (Q) this;
    }

    /**
     * 添加id大于等于条件
     *
     * @param id 用户ID
     * @return UserQuery实例，支持链式调用
     */
    public Q idGreaterThanOrEqualTo(K id) {
        if (id != null) {
            this.expressions.add(new Expression(ID, Operator.GreaterThanOrEqualTo, List.of(id)));
        }
        return (Q) this;
    }

    /**
     * 添加id小于等于条件
     *
     * @param id 用户ID
     * @return UserQuery实例，支持链式调用
     */
    public Q idLessThanOrEqualTo(K id) {
        if (id != null) {
            this.expressions.add(new Expression(ID, Operator.LessThanOrEqualTo, List.of(id)));
        }
        return (Q) this;
    }

    /**
     * 添加id IN条件
     *
     * @param ids 用户ID列表
     * @return UserQuery实例，支持链式调用
     */
    public Q idIn(List<K> ids) {
        if (ids != null && !ids.isEmpty()) {
            this.expressions.add(new Expression(ID, Operator.In, List.of(ids)));
        }
        return (Q) this;
    }

    /**
     * 添加id NOT IN条件
     *
     * @param ids 用户ID列表
     * @return UserQuery实例，支持链式调用
     */
    public Q idNotIn(List<K> ids) {
        if (ids != null && !ids.isEmpty()) {
            this.expressions.add(new Expression(ID, Operator.NotIn, List.of(ids)));
        }
        return (Q) this;
    }

    /**
     * 添加id IS NULL条件
     *
     * @return UserQuery实例，支持链式调用
     */
    public Q idIsNull() {
        this.expressions.add(new Expression(ID, Operator.IsNull, List.of()));
        return (Q) this;
    }

    /**
     * 添加id IS NOT NULL条件
     *
     * @return UserQuery实例，支持链式调用
     */
    public Q idIsNotNull() {
        this.expressions.add(new Expression(ID, Operator.IsNotNull, List.of()));
        return (Q) this;
    }

    /**
     * 添加id BETWEEN条件
     *
     * @param start 起始值
     * @param end   结束值
     * @return UserQuery实例，支持链式调用
     */
    public Q idBetween(K start, K end) {
        if (start != null && end != null) {
            this.expressions.add(new Expression(ID, Operator.Between, List.of(start, end)));
        }
        return (Q) this;
    }

    // ---------------------- id 条件 end ----------------------

    // ---------------------- gmtCreate 条件 start ----------------------

    /**
     * 添加gmtCreate等于条件
     *
     * @param gmtCreate 创建时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateEqualTo(LocalDateTime gmtCreate) {
        if (gmtCreate != null) {
            this.expressions.add(new Expression(GMT_CREATE, Operator.EqualTo, List.of(gmtCreate)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtCreate不等于条件
     *
     * @param gmtCreate 创建时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateNotEqualTo(LocalDateTime gmtCreate) {
        if (gmtCreate != null) {
            this.expressions.add(new Expression(GMT_CREATE, Operator.NotEqualTo, List.of(gmtCreate)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtCreate大于条件
     *
     * @param gmtCreate 创建时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateGreaterThan(LocalDateTime gmtCreate) {
        if (gmtCreate != null) {
            this.expressions.add(new Expression(GMT_CREATE, Operator.GreaterThan, List.of(gmtCreate)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtCreate小于条件
     *
     * @param gmtCreate 创建时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateLessThan(LocalDateTime gmtCreate) {
        if (gmtCreate != null) {
            this.expressions.add(new Expression(GMT_CREATE, Operator.LessThan, List.of(gmtCreate)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtCreate大于等于条件
     *
     * @param gmtCreate 创建时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateGreaterThanOrEqualTo(LocalDateTime gmtCreate) {
        if (gmtCreate != null) {
            this.expressions.add(new Expression(GMT_CREATE, Operator.GreaterThanOrEqualTo, List.of(gmtCreate)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtCreate小于等于条件
     *
     * @param gmtCreate 创建时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateLessThanOrEqualTo(LocalDateTime gmtCreate) {
        if (gmtCreate != null) {
            this.expressions.add(new Expression(GMT_CREATE, Operator.LessThanOrEqualTo, List.of(gmtCreate)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtCreate IN条件
     *
     * @param gmtCreates 创建时间列表
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateIn(List<LocalDateTime> gmtCreates) {
        if (gmtCreates != null && !gmtCreates.isEmpty()) {
            this.expressions.add(new Expression(GMT_CREATE, Operator.In, List.of(gmtCreates)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtCreate NOT IN条件
     *
     * @param gmtCreates 创建时间列表
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateNotIn(List<LocalDateTime> gmtCreates) {
        if (gmtCreates != null && !gmtCreates.isEmpty()) {
            this.expressions.add(new Expression(GMT_CREATE, Operator.NotIn, List.of(gmtCreates)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtCreate IS NULL条件
     *
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateIsNull() {
        this.expressions.add(new Expression(GMT_CREATE, Operator.IsNull, List.of()));
        return (Q) this;
    }

    /**
     * 添加gmtCreate IS NOT NULL条件
     *
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateIsNotNull() {
        this.expressions.add(new Expression(GMT_CREATE, Operator.IsNotNull, List.of()));
        return (Q) this;
    }

    /**
     * 添加gmtCreate BETWEEN条件
     *
     * @param start 起始时间
     * @param end   结束时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtCreateBetween(LocalDateTime start, LocalDateTime end) {
        if (start != null && end != null) {
            this.expressions.add(new Expression(GMT_CREATE, Operator.Between, List.of(start, end)));
        }
        return (Q) this;
    }

    // ---------------------- gmtCreate 条件 end ----------------------

    // ---------------------- gmtModified 条件 start ----------------------

    /**
     * 添加gmtModified等于条件
     *
     * @param gmtModified 修改时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedEqualTo(LocalDateTime gmtModified) {
        if (gmtModified != null) {
            this.expressions.add(new Expression(GMT_MODIFIED, Operator.EqualTo, List.of(gmtModified)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtModified不等于条件
     *
     * @param gmtModified 修改时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedNotEqualTo(LocalDateTime gmtModified) {
        if (gmtModified != null) {
            this.expressions.add(new Expression(GMT_MODIFIED, Operator.NotEqualTo, List.of(gmtModified)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtModified大于条件
     *
     * @param gmtModified 修改时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedGreaterThan(LocalDateTime gmtModified) {
        if (gmtModified != null) {
            this.expressions.add(new Expression(GMT_MODIFIED, Operator.GreaterThan, List.of(gmtModified)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtModified小于条件
     *
     * @param gmtModified 修改时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedLessThan(LocalDateTime gmtModified) {
        if (gmtModified != null) {
            this.expressions.add(new Expression(GMT_MODIFIED, Operator.LessThan, List.of(gmtModified)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtModified大于等于条件
     *
     * @param gmtModified 修改时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedGreaterThanOrEqualTo(LocalDateTime gmtModified) {
        if (gmtModified != null) {
            this.expressions.add(new Expression(GMT_MODIFIED, Operator.GreaterThanOrEqualTo, List.of(gmtModified)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtModified小于等于条件
     *
     * @param gmtModified 修改时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedLessThanOrEqualTo(LocalDateTime gmtModified) {
        if (gmtModified != null) {
            this.expressions.add(new Expression(GMT_MODIFIED, Operator.LessThanOrEqualTo, List.of(gmtModified)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtModified IN条件
     *
     * @param gmtModifieds 修改时间列表
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedIn(List<LocalDateTime> gmtModifieds) {
        if (gmtModifieds != null && !gmtModifieds.isEmpty()) {
            this.expressions.add(new Expression(GMT_MODIFIED, Operator.In, List.of(gmtModifieds)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtModified NOT IN条件
     *
     * @param gmtModifieds 修改时间列表
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedNotIn(List<LocalDateTime> gmtModifieds) {
        if (gmtModifieds != null && !gmtModifieds.isEmpty()) {
            this.expressions.add(new Expression(GMT_MODIFIED, Operator.NotIn, List.of(gmtModifieds)));
        }
        return (Q) this;
    }

    /**
     * 添加gmtModified IS NULL条件
     *
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedIsNull() {
        this.expressions.add(new Expression(GMT_MODIFIED, Operator.IsNull, List.of()));
        return (Q) this;
    }

    /**
     * 添加gmtModified IS NOT NULL条件
     *
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedIsNotNull() {
        this.expressions.add(new Expression(GMT_MODIFIED, Operator.IsNotNull, List.of()));
        return (Q) this;
    }

    /**
     * 添加gmtModified BETWEEN条件
     *
     * @param start 起始时间
     * @param end   结束时间
     * @return UserQuery实例，支持链式调用
     */
    public Q gmtModifiedBetween(LocalDateTime start, LocalDateTime end) {
        if (start != null && end != null) {
            this.expressions.add(new Expression(GMT_MODIFIED, Operator.Between, List.of(start, end)));
        }
        return (Q) this;
    }

    // ---------------------- gmtModified 条件 end ----------------------


    // ---------------------- order start ----------------------

    public Q orderBy(String javaFieldName, Order order) {
        if (javaFieldName != null && order != null && this.fieldMap.containsKey(javaFieldName)) {
            this.orders.add(new OrderItem(this.fieldMap.get(javaFieldName), order));
        }
        return (Q) this;
    }


    public Q orderBy(ColumnName columnName, Order order) {
        if (columnName != null && order != null) {
            this.orders.add(new OrderItem(columnName, order));
        }
        return (Q) this;
    }

    // ---------------------- order end ----------------------

    protected void addExpression(ColumnName columnName, Operator operator, Object... value) {
        if (columnName != null && operator != null) {
            this.expressions.add(new Expression(columnName, operator, value == null ? List.of() : List.of(value)));
        }
    }

    protected void initFieldMap() {
        addField(ID);
        addField(GMT_CREATE);
        addField(GMT_MODIFIED);
    }

    protected void addField(ColumnName columnName) {
        if (columnName != null) {
            fieldMap.put(columnName.getJavaFieldName(), columnName);
        }
    }

    protected Map<String, ColumnName> getFieldMap() {
        return Map.copyOf(fieldMap);
    }
}
